home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / wired movies and sprites / qtsprites / qtsprites.c < prev    next >
Encoding:
Text File  |  2000-09-28  |  11.5 KB  |  381 lines

  1. //////////
  2. //
  3. //    File:        QTSprites.c
  4. //
  5. //    Contains:    QuickTime sprites support for QuickTime movies.
  6. //
  7. //    Written by:    ???
  8. //    Revised by:    Deeje Cooley and Tim Monroe
  9. //                Based (heavily!) on the existing MakeSpriteMovie.c code written by ???.
  10. //
  11. //    Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  12. //
  13. //    Change History (most recent first):
  14. //
  15. //       <4>         09/30/98    rtm        tweaked call to AddMovieResource to create single-fork movies
  16. //       <3>         06/19/98    rtm        moved to new routine names (e.g. SpriteMediaSetSpriteProperty)
  17. //       <2>         04/09/98    rtm        added sprite hit-testing
  18. //       <1>         04/02/98    rtm        first file; integrated existing code with shell framework
  19. //       
  20. //    This sample code creates a sprite movie containing one sprite track. The sprite track contains
  21. //    a static background picture sprite (or just a colored background, depending on the value of the
  22. //    global variable gUseBackgroundPicture) and three other sprites that change their properties over time.
  23. //    The track's media contains only one key frame sample followed by many override samples. The key
  24. //    frame contains all of the images used by the sprites; the override frames only contain the overrides
  25. //    of the locations, image indices, and layers needed for the other sprites.
  26. //
  27. //    This sample code also shows how to hit test sprites. It uses the function SpriteMediaHitTestAllSprites
  28. //    to find mouse clicks on the sprites in the first sprite track in a movie. If the user clicks on a
  29. //    sprite, we toggle the visibility state of the sprite. You would probably want to do something a bit
  30. //    more interesting when the user clicks on a sprite.
  31. //
  32. //////////
  33.  
  34.  
  35. // header files
  36. #include "QTSprites.h"
  37.  
  38. // global variables
  39. Boolean                         gUseBackgroundPicture = true;        // do we display a background picture?
  40.  
  41.  
  42. ApplicationDataHdl QTSprites_InitWindowData (WindowObject theWindowObject)
  43. {
  44.     ApplicationDataHdl        myAppData = NULL;
  45.     Track                    myTrack = NULL;
  46.     MediaHandler            myHandler = NULL;
  47.  
  48.     myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
  49.     if (myAppData != NULL) {
  50.     
  51.         myTrack = GetMovieIndTrackType((**theWindowObject).fMovie, 1, SpriteMediaType, movieTrackMediaType | movieTrackEnabledOnly);
  52.         if (myTrack != NULL)
  53.             myHandler = GetMediaHandler(GetTrackMedia(myTrack));
  54.     
  55.         // remember the sprite media handler
  56.         (**myAppData).fMovieHasSprites = (myTrack != NULL);
  57.         (**myAppData).fSpriteHandler = myHandler;
  58.     }
  59.     
  60.     return(myAppData);
  61. }
  62.  
  63.  
  64. //////////
  65. //
  66. // QTSprites_DumpWindowData
  67. // Get rid of any window-specific data for the sprite media handler.
  68. //
  69. //////////
  70.  
  71. void QTSprites_DumpWindowData (WindowObject theWindowObject)
  72. {
  73.     ApplicationDataHdl        myAppData = NULL;
  74.         
  75.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  76.     if (myAppData != NULL)
  77.         DisposeHandle((Handle)myAppData);
  78. }
  79.  
  80.  
  81. //////////
  82. //
  83. // QTSprites_CreateSpritesMovie
  84. // Create a QuickTime movie containing a sprite track.
  85. //
  86. //////////
  87.  
  88. OSErr QTSprites_CreateSpritesMovie (void)
  89. {
  90.     short                    myResRefNum = 0;
  91.     short                    myResID = movieInDataForkResID;
  92.     Movie                    myMovie = NULL;
  93.     Track                    myTrack;
  94.     Media                    myMedia;
  95.     StandardFileReply        myReply;
  96.     QTAtomContainer            mySample = NULL;
  97.     QTAtomContainer            mySpriteData = NULL;
  98.     RGBColor                myKeyColor;
  99.     Point                    myLocation, myIconLocation;
  100.     short                    isVisible, myLayer, myIndex, i, myDelta, myIconMinH, myIconMaxH;
  101.     long                    myFlags = createMovieFileDeleteCurFile | createMovieFileDontCreateResFile;
  102.     OSErr                    myErr = noErr;
  103.  
  104.     //////////
  105.     //
  106.     // create a new movie file
  107.     //
  108.     //////////
  109.  
  110.     // ask the user for the name of the new movie file
  111.     StandardPutFile("\pSprite movie file name:", "\pSprite.mov", &myReply);
  112.     if (!myReply.sfGood)
  113.         goto bail;
  114.  
  115.     // create a movie file for the destination movie
  116.     myErr = CreateMovieFile(&myReply.sfFile, FOUR_CHAR_CODE('TVOD'), smSystemScript, myFlags, &myResRefNum, &myMovie);
  117.     if (myErr != noErr)
  118.         goto bail;
  119.     
  120.     //////////
  121.     //
  122.     // create the sprite track and media
  123.     //
  124.     //////////
  125.     
  126.     myTrack = NewMovieTrack(myMovie, ((long)kSpriteTrackWidth << 16), ((long)kSpriteTrackHeight << 16), kNoVolume);
  127.     myMedia = NewTrackMedia(myTrack, SpriteMediaType, kSpriteMediaTimeScale, NULL, 0);
  128.  
  129.     //////////
  130.     //
  131.     // create a key frame sample containing the sprites and all of their shared images
  132.     //
  133.     //////////
  134.  
  135.     // create a new, empty key frame sample
  136.     myErr = QTNewAtomContainer(&mySample);
  137.     if (myErr != noErr)
  138.         goto bail;
  139.  
  140.     myKeyColor.red = myKeyColor.green = myKeyColor.blue = 0xffff;        // white
  141.  
  142.     // add images to the key frame sample
  143.     AddPICTImageToKeyFrameSample(mySample, kIconPictID, &myKeyColor, kIconImageIndex, NULL, NULL);
  144.     AddPICTImageToKeyFrameSample(mySample, kWorldPictID, &myKeyColor, kWorldImageIndex, NULL, NULL);
  145.     AddPICTImageToKeyFrameSample(mySample, kBackgroundPictID, &myKeyColor, kBackgroundImageIndex, NULL, NULL);
  146.     for (myIndex = 1; myIndex <= kNumSpaceShipImages; myIndex++)
  147.         AddPICTImageToKeyFrameSample(mySample, kFirstSpaceShipPictID + myIndex - 1, &myKeyColor, myIndex + 3, NULL, NULL);
  148.  
  149.     //////////
  150.     //
  151.     // add samples to the sprite track's media
  152.     //
  153.     //////////
  154.     
  155.     BeginMediaEdits(myMedia);
  156.  
  157.     myErr = QTNewAtomContainer(&mySpriteData);
  158.     if (myErr != noErr)
  159.         goto bail;
  160.  
  161.     // the background image
  162.     if (gUseBackgroundPicture) {
  163.         myLocation.h    = 0;
  164.         myLocation.v    = 0;
  165.         isVisible        = true;
  166.         myLayer            = kBackgroundSpriteLayerNum;            // this makes the sprite a background sprite
  167.         myIndex            = kBackgroundImageIndex;
  168.         myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
  169.         if (myErr != noErr)
  170.             goto bail;
  171.         AddSpriteToSample(mySample, mySpriteData, kBackgroundSpriteAtomID);
  172.     }
  173.  
  174.     // the space ship sprite
  175.     myLocation.h     = 0;
  176.     myLocation.v    = 60;
  177.     isVisible        = true;
  178.     myLayer            = -1;
  179.     myIndex            = kFirstSpaceShipImageIndex;
  180.     myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
  181.     if (myErr != noErr)
  182.         goto bail;
  183.     AddSpriteToSample(mySample, mySpriteData, kSpaceShipSpriteAtomID);
  184.  
  185.     // the world sprite
  186.     myLocation.h     = (kSpriteTrackWidth / 2) - 24;
  187.     myLocation.v    = (kSpriteTrackHeight / 2) - 24;
  188.     isVisible        = true;
  189.     myLayer            = 1;
  190.     myIndex            = kWorldImageIndex;
  191.     myErr = SetSpriteData(mySpriteData, &myLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
  192.     if (myErr != noErr)
  193.         goto bail;
  194.     AddSpriteToSample(mySample, mySpriteData, kWorldSpriteAtomID);
  195.  
  196.     // the icon sprite
  197.     myIconMinH            = (kSpriteTrackWidth / 2) - 116;
  198.     myIconMaxH            = myIconMinH + 200;
  199.     myDelta                = 2;
  200.     myIconLocation.h     = myIconMinH;
  201.     myIconLocation.v    = (kSpriteTrackHeight / 2) - (24 + 12);
  202.     isVisible            = true;
  203.     myLayer                = 0;
  204.     myIndex                = kIconImageIndex;
  205.     myErr = SetSpriteData(mySpriteData, &myIconLocation, &isVisible, &myLayer, &myIndex, NULL, NULL, NULL);
  206.     if (myErr != noErr)
  207.         goto bail;
  208.     AddSpriteToSample(mySample, mySpriteData, kIconSpriteAtomID);
  209.     
  210.     // add the key frame sample to the sprite track media
  211.     //
  212.     // to add the sample data in a compressed form, you would use a QuickTime DataCodec to perform the
  213.     // compression; replace the call to the utility AddSpriteSampleToMedia with a call to the utility
  214.     // AddCompressedSpriteSampleToMedia to do this
  215.     
  216.     AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, true, NULL);    
  217.     //AddCompressedSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, true, zlibDataCompressorSubType, NULL);
  218.  
  219.     //////////
  220.     //
  221.     // add a few override samples to move the space ship and icon, and to change the icon's layer
  222.     //
  223.     //////////
  224.  
  225.     // original space ship location
  226.     myIndex            = kFirstSpaceShipImageIndex;
  227.     myLocation.h     = 0;
  228.     myLocation.v     = 80;
  229.     isVisible        = true;
  230.     
  231.     for (i = 1; i <= kNumOverrideSamples; i++) {
  232.         QTRemoveChildren(mySample, kParentAtomIsContainer);
  233.         QTRemoveChildren(mySpriteData, kParentAtomIsContainer);
  234.  
  235.         // every third frame, bump the space ship's image index (so that it spins as it moves)
  236.         if ((i % 3) == 0) {
  237.             myIndex++;
  238.             if (myIndex > kLastSpaceShipImageIndex)
  239.                 myIndex = kFirstSpaceShipImageIndex;
  240.         }
  241.  
  242.         // every frame, bump the space ship's location (so that it moves as it spins)
  243.         myLocation.h += 2;
  244.         myLocation.v += 1;
  245.         
  246.         if (isVisible)
  247.             SetSpriteData(mySpriteData, &myLocation, NULL, NULL, &myIndex, NULL, NULL, NULL);
  248.         else {
  249.             isVisible = true;
  250.             SetSpriteData(mySpriteData, &myLocation, &isVisible, NULL, &myIndex, NULL, NULL, NULL);
  251.         }
  252.                 
  253.         AddSpriteToSample(mySample, mySpriteData, 2);
  254.         
  255.         // make the icon move and change layer
  256.         QTRemoveChildren(mySpriteData, kParentAtomIsContainer);
  257.         myIconLocation.h += myDelta;
  258.         
  259.         if (myIconLocation.h >= myIconMaxH ) {
  260.             myIconLocation.h = myIconMaxH;
  261.             myDelta = -myDelta;
  262.         }
  263.         
  264.         if (myIconLocation.h <= myIconMinH ) {
  265.             myIconLocation.h = myIconMinH;
  266.             myDelta = -myDelta;
  267.         }
  268.         
  269.         if (myDelta > 0)
  270.             myLayer = 0;
  271.         else
  272.             myLayer = 3;
  273.             
  274.         SetSpriteData(mySpriteData, &myIconLocation, NULL, &myLayer, NULL, NULL, NULL, NULL);
  275.         AddSpriteToSample(mySample, mySpriteData, 4);
  276.         
  277.         AddSpriteSampleToMedia(myMedia, mySample, kSpriteMediaFrameDuration, false, NULL);    
  278.     }
  279.  
  280.     EndMediaEdits(myMedia);
  281.     
  282.     // add the media to the track
  283.     InsertMediaIntoTrack(myTrack, 0, 0, GetMediaDuration(myMedia), fixed1);
  284.     
  285.     //////////
  286.     //
  287.     // set the sprite track properties
  288.     //
  289.     //////////
  290.     
  291.     if (!gUseBackgroundPicture) {
  292.         QTAtomContainer        myTrackProperties;
  293.         RGBColor            myBackgroundColor;
  294.         
  295.         // add a background color to the sprite track
  296.         myBackgroundColor.red = EndianU16_NtoB(0x8000);
  297.         myBackgroundColor.green = EndianU16_NtoB(0);
  298.         myBackgroundColor.blue = EndianU16_NtoB(0xffff);
  299.         
  300.         QTNewAtomContainer(&myTrackProperties);
  301.         QTInsertChild(myTrackProperties, 0, kSpriteTrackPropertyBackgroundColor, 1, 1, sizeof(RGBColor), &myBackgroundColor, NULL);
  302.  
  303.         myErr = SetMediaPropertyAtom(myMedia, myTrackProperties);
  304.         if (myErr != noErr)
  305.             goto bail;
  306.  
  307.         QTDisposeAtomContainer(myTrackProperties);
  308.     }
  309.     
  310.     //////////
  311.     //
  312.     // finish up
  313.     //
  314.     //////////
  315.     
  316.     // add the movie resource to the movie file
  317.     myErr = AddMovieResource(myMovie, myResRefNum, &myResID, myReply.sfFile.name);
  318.     
  319. bail:
  320.     if (mySample != NULL)
  321.         QTDisposeAtomContainer(mySample);
  322.  
  323.     if (mySpriteData != NULL)
  324.         QTDisposeAtomContainer(mySpriteData);    
  325.             
  326.     if (myResRefNum != 0)
  327.         CloseMovieFile(myResRefNum);
  328.  
  329.     if (myMovie != NULL)
  330.         DisposeMovie(myMovie);
  331.         
  332.     return(myErr);
  333. }
  334.  
  335.  
  336. //////////
  337. //
  338. // QTSprites_HitTestSprites
  339. // Determine whether a mouse click is on a sprite; return true if it is, false otherwise.
  340. //
  341. // This routine is intended to be called from your movie controller action filter function,
  342. // in response to mcActionMouseDown actions.
  343. //
  344. //////////
  345.  
  346. Boolean QTSprites_HitTestSprites (WindowObject theWindowObject, EventRecord *theEvent)
  347. {
  348.     ApplicationDataHdl        myAppData = NULL;
  349.     MediaHandler            myHandler = NULL;
  350.     Boolean                    isHandled = false;
  351.     long                    myFlags = 0L;
  352.     QTAtomID                myAtomID = 0;
  353.     Point                    myPoint;
  354.     ComponentResult            myErr = noErr;
  355.  
  356.     myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
  357.     if (myAppData == NULL)
  358.         goto bail;
  359.         
  360.     if (theEvent == NULL)
  361.         goto bail;
  362.         
  363.     myHandler = (**myAppData).fSpriteHandler;
  364.     myFlags = spriteHitTestImage | spriteHitTestLocInDisplayCoordinates | spriteHitTestInvisibleSprites;
  365.     myPoint = theEvent->where;
  366.     
  367.     myErr = SpriteMediaHitTestAllSprites(myHandler, myFlags, myPoint, &myAtomID);
  368.     if ((myErr == noErr) && (myAtomID != 0)) {
  369.         Boolean                isVisible;
  370.         
  371.         // the user has clicked on a sprite;
  372.         // for now, we'll just toggle the visibility state of the sprite
  373.         SpriteMediaGetSpriteProperty(myHandler, myAtomID, kSpritePropertyVisible, (void *)&isVisible);
  374.         SpriteMediaSetSpriteProperty(myHandler, myAtomID, kSpritePropertyVisible, (void *)!isVisible);
  375.  
  376.         isHandled = true;
  377.     }
  378.  
  379. bail:
  380.     return(isHandled);
  381. }